package com.zijidelu.luframework.domain.model.entity;

import com.zijidelu.luframework.constant.ClassNameConstant;
import com.zijidelu.luframework.utils.lang.reflect.generic.GenericResolveUtil;

/**
 * 表示一个聚合（Aggregate）内部的实体关系。
 * <p>
 * 此关系定义了聚合根（Root）如何与它的子实体通过特定字段进行关联。
 * 注意：所有类型均为 {@link Class}，代表实体类的元信息，而非实例。
 *
 * @param rootType        聚合根的类型，如 Order.class。这是关系的起始点和控制中心。
 * @param childType       聚合内部子实体的类型，如 OrderItem.class。
 * @param childForeignKey 子实体中持有对聚合根引用的字段名，如 "order"。
 *                        该字段是实现关系映射的关键。
 * @author ZIJIDELU
 */
public record EntityRelation(Class<?> rootType, Class<?> childType, String childForeignKey) {

    /**
     * 紧凑构造器
     * 自动计算子实体关联父实体字段名
     */
    private EntityRelation(Class<?> rootEntityClass, Class<?> childEntityClass) {
        this(
                rootEntityClass,
                childEntityClass,
                ClassNameConstant.calcDomainName(rootEntityClass) + "Id"
        );

    }

    /**
     * 创建实体关系
     */
    public static EntityRelation of(Class<?> rootEntityClass, Class<?> childEntityClass) {
        validateRootEntityClass(rootEntityClass);
        validateRootEntityClass(childEntityClass);

        // 检查子实体的第一个泛型参数是否为父实体类
        final Class<?> rawType = EntityRelation.calcRootEntityType(childEntityClass);
        if (rawType != rootEntityClass) {
            throw new IllegalArgumentException("Child entity class must implement ChildEntity interface with parent entity class " + rootEntityClass.getSimpleName());
        }

        return new EntityRelation(rootEntityClass, childEntityClass);
    }

    /**
     * 判断是否为实体类
     */
    public static boolean isEntity(final Class<?> candidate) {
        return candidate != null && Entity.class.isAssignableFrom(candidate);
    }

    /**
     * 判断是否为子实体类
     */
    public static boolean isChildEntity(final Class<?> candidate) {
        return isEntity(candidate) && ChildEntity.class.isAssignableFrom(candidate);
    }

    /**
     * 验证父实体类是否符合要求
     */
    public static Class<?> validateRootEntityClass(Class<?> rootEntityClass) {
        if (rootEntityClass == null) {
            throw new IllegalArgumentException("Argument cannot be null");
        }
        if (!Entity.class.isAssignableFrom(rootEntityClass)) {
            throw new IllegalArgumentException("Root entity class must implement Entity interface");
        }

        return rootEntityClass;
    }

    /**
     * 验证子实体类是否符合要求
     */
    public static Class<?> validateChildEntityClass(Class<?> childEntityClass) {
        if (childEntityClass == null) {
            throw new IllegalArgumentException("Argument cannot be null");
        }
        if (!Entity.class.isAssignableFrom(childEntityClass)) {
            throw new IllegalArgumentException("Child entity class must implement Entity interface");
        }
        if (!ChildEntity.class.isAssignableFrom(childEntityClass)) {
            throw new IllegalArgumentException("Child entity class must implement ChildEntity interface");
        }

        return childEntityClass;
    }

    /**
     * 获取父实体Class
     */
    public static Class<?> calcRootEntityType(Class<?> childEntityClass) {
        validateChildEntityClass(childEntityClass);

        // 检查子实体的第一个泛型参数是否为父实体类
        final Class<?> rawType = GenericResolveUtil.getRawType(GenericResolveUtil.resolveGenericsWithCache(childEntityClass, ChildEntity.class).getFirst());
        if (rawType == null) {
            throw new IllegalArgumentException("Child entity class must implement ChildEntity interface with parent entity class");
        }

        return rawType;
    }

    /**
     * 获取父实体名称
     */
    public String getRootName() {
        return rootType.getSimpleName();
    }

    /**
     * 获取子实体名称
     */
    public String getChildName() {
        return childType.getSimpleName();
    }

    /**
     * 获取关系描述
     */
    public String getDescription() {
        return String.format("%s -> %s (字段: %s)", getRootName(), getChildName(), childForeignKey);
    }

}
